import org.codehaus.groovy.runtime.GStringImpl

println "hello, world"
for (arg in this.args) {
    println "Argument:" + arg;
}
// this is a comment
/* a block comment, commenting out an
alternative to above:
this.args.each{ arg -> println "hello,
${arg}"}
*/

// list
def list = [1, 2, 'hello', new
        java.util.Date()]
assert list.size() == 4
assert list.get(2) == 'hello'
assert list[2] == 'hello'

def list2 = [1, 2, 3]
for (i in list2) {
    println i
}

def list3 = [*list2, 4, 5, 6] // Spread list elements
println list3
println list3[2..4]

def names = ['Grace', 'Rob', 'Emmy']
assert ('Emmy' in names)

// map
def map = ['name'    : 'James',
           'location': 'London']
assert map.size() == 2
assert map.get('name') == 'James'
assert map['name'] == 'James'

def m1 = [c: 3, d: 4]
def m2 = [a: 1, b: 2, *: m1, d: 8]
assert m2 == [a: 1, b: 2, c: 3, d: 8]

// GString
def key = "a"
def m = ["${key}": "letter ${key}"]

println "${key}"
println "${key}".getClass()
assert m["a"] == null  // the map is created with an initial pair whose key is a GString
println m
println m["${key}"]
println m.getClass()

def name = 'Groovy'
def template = """
    Dear Mr ${name},

    You're the winner of the lottery!

    Yours sincerly,

    Dave
"""
println template.getClass()

// more list, and it closures
def numbers = [1, 2, 3]

numbers.each {
    if (it == 2) return
    println "numbers " + it
}

assert numbers instanceof List
assert numbers.size() == 3

println numbers
println numbers * 2
//println numbers ** 2  // wrong
println numbers*.power(2)  // Spread operator
println numbers.collect({ it**2 + 1 })

// Elvis operator
user_name = null
println user_name ?: 'Anonymous'  // user_name ? user_name : 'Anonymous'
user_name = "scott"
println user_name ?: 'Anonymous'  // user_name ? user_name : 'Anonymous'

// Object
class User {
    public final String name

    User(String name) { this.name = name }

    String getName() { "Name: $name" }
}

def user = new User('Bob')
assert user.name == 'Name: Bob'
assert user.@name == 'Bob'

// method pointer
def str = 'example of method reference'
def fun = str.&toUpperCase
def upper = fun()
assert upper == str.toUpperCase()

// range
def range = 0..5
assert (0..5).collect() == [0, 1, 2, 3, 4, 5]
assert (0..<5).collect() == [0, 1, 2, 3, 4]
assert (0..5) instanceof List
assert (0..5).size() == 6

// The spaceship operator (<=>) delegates to the compareTo method:
assert (1 <=> 1) == 0
assert (1 <=> 2) == -1
assert (2 <=> 1) == 1

// as
Integer x = 123
//String s = (String) x // same bellow
String s = x as String
println s

// call
class MyCallable {
    int call(int x) {
        2 * x
    }
}

def mc = new MyCallable()
assert mc.call(2) == 4
assert mc(2) == 4
